#pragma once 

#include"thread.hpp"
#include"Lockguard.hpp"
#include<vector>
#include<queue>
#include<mutex>
#include<pthread.h>
#include<unistd.h>


using namespace std;
#define N 10
template <class T>
class Threadpool;

template<class T>
class ThreadData//为了获取线程的名称
{
    
public:

  
  Threadpool<T> *threadpool;
  string name;
public:  
  ThreadData(Threadpool<T> *tp, const std::string &n) : threadpool(tp), name(n)
    {
    }

};

template <class T>

class Threadpool
{ private:
  static void* handlerTask(void * args)//每个线程都需要执行的函数,目的是为了串行的拿任务
  { ThreadData<T>* td=(ThreadData<T>*) args;//参数为对线程池封装后，具有线程池和线程池名称的对象
    while(true)
    {
         T t;//用于接收任务
         { Lockguard guard(td->threadpool->mutex());//先多个线程进行竞争锁
            while(td->threadpool->isempty())//判断是否有任务
            {
                td->threadpool->threadwait();//没用任务就阻塞等待任务，把锁给其他线程，目的是让其它线程去存任务
            }
          t= td->threadpool->pop();//此时有任务，就可以进行取出       
         }
         t();
    }
    
    return nullptr;



  }
  
    Threadpool(const int &size=N):_num(size)//根据传递的传递的线程数量来制定
    { pthread_mutex_init(&_mutex,nullptr);//对锁初始化
      pthread_cond_init(&_cond,nullptr);//对条件变量初始化
      for(int i=0;i<_num;i++)//添加线程到数组
      {
        _tp.push_back(new Thread());//新建线程
      }
    }
    void operator=(const Threadpool &) = delete;//用于显式禁用某个成员函数
    Threadpool(const Threadpool &) = delete;

public:
bool isempty()//判断任务队列是否为空
  {
    return _q.empty();
  }
  void threadwait(){pthread_cond_wait(&_cond,&_mutex);}

 T pop()//拿任务的操作
 {
    T t=_q.front();
    _q.pop();
    return t;
 }
 pthread_mutex_t *mutex()//获取类中唯一锁的地址
 {
    return &_mutex;
 }
public:
void run()//初始化数组中的线程
{   for(auto &t :_tp)//遍历数组
    {ThreadData<T>* td= new ThreadData<T>(this,t->threadname());//通过td来调用线程数组，因为可以对线程取名
      t->start(handlerTask,td);//传入线程需要进行阻塞取任务和执行任务的过程函数以及参数，还有线程的创建
      //logMessage(DEBUG, "%s start ...", t->threadname().c_str());//多参数日志的调用，
    }



}
  void push (const T &in)//插入任务到线程池的队列中
  {   Lockguard guard(&_mutex);//存任务也是串行执行的
      _q.push(in);
      pthread_cond_signal(&_cond);//传递了任务进入队列，说明此时队列不为空，有任务可以执行，因此满足条件变量，可以进行唤醒线程。
  }
  ~Threadpool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (const auto &t : _tp)
        delete t;
    }
 static Threadpool<T> *getInstance()//获取单例模式
 { 
   if(nullptr==tp)
   { std::lock_guard<std::mutex> lock(_singlock);//加锁
     if(nullptr==tp)
     {
        tp=new Threadpool<T>();
     }
    
   }
return tp;
 }
 
  


private:
   int _num;//数组的线程数量
   vector<Thread*> _tp;//存放多个线程信息的数组。
    queue<T> _q;//存放任务的队列，先进先出
    pthread_mutex_t _mutex;//共用一把锁
    pthread_cond_t _cond;//共用一个成员变量
   static Threadpool<T> *tp;//单例实例指针
   static std::mutex _singlock;//用于单例的互斥锁
};

template <class T>
Threadpool<T> *Threadpool<T>::tp = nullptr;

template <class T>
std::mutex Threadpool<T>::_singlock;

